package cn.edu.ctbu.service.impl;

import cn.edu.ctbu.DTO.OrderDTO;
import cn.edu.ctbu.DTO.OrderDishNameandCount;
import cn.edu.ctbu.DTO.PaySuccessDTO;
import cn.edu.ctbu.DTO.RejectOrdersDTO;
import cn.edu.ctbu.VO.*;
import cn.edu.ctbu.entity.*;
import cn.edu.ctbu.mapper.OrdersMapper;
import cn.edu.ctbu.service.*;
import cn.edu.ctbu.utils.JWTUtils;
import cn.edu.ctbu.utils.WebSocketServer;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import io.jsonwebtoken.Claims;
import jakarta.servlet.http.HttpServletRequest;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.io.IOException;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.concurrent.ThreadLocalRandom;

/**
 * <p>
 * 订单表 服务实现类
 * </p>
 *
 * @author author
 * @since 2024-05-12
 */
@Service
public class OrdersServiceImpl extends ServiceImpl<OrdersMapper, Orders> implements IOrdersService {

    @Autowired
    IOrderDetailService iOrderDetailService;
    @Autowired
    IDishService iDishService;
    @Autowired
    ISetmealService iSetmealService;
    @Autowired
    IAddressBookService iAddressBookService;
    @Autowired
    IUserService iUserService;
    @Autowired
    HttpServletRequest httpServletRequest;
    @Autowired
    IShoppingCartService iShoppingCartService;
    @Autowired
    WebSocketServer webSocketServer;

    @Override
    public List<OrdersVO> get(String number, String phone, LocalDate startTime, LocalDate endTime) {
        QueryWrapper wrapper = new QueryWrapper<>();
        if (number != null) {
            wrapper.like("number", number);
        }
        if (phone != null) {
            wrapper.like("phone", phone);
        }
        if (startTime != null) {
            wrapper.ge("order_time", startTime);
        }
        if (endTime != null) {
            wrapper.le("order_time", endTime);
        }
        List<Orders> orders = list(wrapper);

        List<OrdersVO> vo = new ArrayList<>();
        //寻找菜品信息
        for (Orders order : orders) {
            String s = dishString(order.getId());
            OrdersVO ordersVO = new OrdersVO();
            BeanUtils.copyProperties(order, ordersVO);
            ordersVO.setOrderDishes(String.valueOf(s));
            vo.add(ordersVO);
        }
        return vo;
    }


    /**
     * 根据订单号生成菜品字符串
     */
    public String dishString(Long orderId){
        QueryWrapper wrapper = new QueryWrapper<>().eq("order_id", orderId);
        List<OrderDetail> orderDetails = iOrderDetailService.list(wrapper);
        StringBuilder s = new StringBuilder();
        for (OrderDetail orderDetail:orderDetails){
            s.append(orderDetail.getName()).append("*").append(orderDetail.getNumber()).append(" ");
        }
//        List<OrderDishMap> dishMaps=new ArrayList<>();
//        if (!orderDetails.isEmpty()) {
//            for (OrderDetail orderDetail : orderDetails) {
//                Boolean flag=false;
//                for (OrderDishMap orderDishMap:dishMaps){
//                    if( orderDishMap.getId().equals(orderDetail.getDishId())){
//                        orderDishMap.setNumber( orderDishMap.getNumber() + orderDetail.getNumber());
//                        flag=true;
//                    }
//                }
//                if (!flag){
//                    OrderDishMap orderDishMap=new OrderDishMap();
//                    orderDishMap.setId(orderDetail.getDishId());
//                    orderDishMap.setName(orderDetail.getName());
//                    orderDishMap.setNumber(orderDetail.getNumber());
//                    dishMaps.add(orderDishMap);
//                }
//            }
//            for (OrderDishMap orderDishMap:dishMaps){
//                s.append(orderDishMap.getName()).append("*").append(orderDishMap.getNumber()).append(" ");
//            }
//        }
        return String.valueOf(s);
    }



    @Override
    public OrderDetailVO detail(Long id) {
        Orders order = getById(id);
        //根据订单号找到订单详情里面对应菜品
        QueryWrapper wrapper=new QueryWrapper<>().eq("order_id",id);
        List<OrderDetail> list = iOrderDetailService.list(wrapper);
        String s = dishString(id);

        //分别赋值
        OrderDetailVO orderDetailVO=new OrderDetailVO();
        BeanUtils.copyProperties(order,orderDetailVO);
        orderDetailVO.setOrderDishes(s);
        orderDetailVO.setOrderDetailList(list);
        return orderDetailVO;
    }

    @Override
    public void receive(Long id) {
        //接单
        Orders orders = getById(id);
        orders.setStatus(3);
        updateById(orders);
    }

    @Override
    public void reject(RejectOrdersDTO dto) {
        //拒单
        Orders orders = getById(dto.getId());
        orders.setStatus(6);
        orders.setRejectionReason(dto.getReason());
        orders.setCancelTime(LocalDateTime.now());
        updateById(orders);
    }

    @Override
    public void delivery(Long id) {
        //派送订单
        Orders orders = getById(id);
        orders.setStatus(4);
        orders.setEstimatedDeliveryTime(LocalDateTime.now().plusMinutes(40));
        updateById(orders);
    }

    @Override
    public void complete(Long id) {
        //完成订单
        Orders orders = getById(id);
        orders.setStatus(5);
        orders.setDeliveryTime(LocalDateTime.now());
        updateById(orders);
    }

    @Override
    public void delete(Long id) {
        //删除订单
        removeById(id);
        QueryWrapper wrapper=new QueryWrapper<>().eq("order_id",id);
        iOrderDetailService.remove(wrapper);
    }

    @Override
    public void cancel(RejectOrdersDTO dto) {
        //取消订单
        Orders orders = getById(dto.getId());
        orders.setStatus(6);
        orders.setCancelReason(dto.getReason());
        orders.setCancelTime(LocalDateTime.now());
        updateById(orders);
    }

    @Override
    public TurnoverVO turnover(LocalDate startTime, LocalDate endTime) {
        TurnoverVO vo=new TurnoverVO();
        List<LocalDate> dateList=new ArrayList<>();
        dateList.add(startTime);
        LocalDate newDate=startTime;
        while (!newDate.equals(endTime)){
            newDate=newDate.plusDays(1);
            dateList.add(newDate);
        }
        List<BigDecimal> amountList=new ArrayList<>();
        for (LocalDate date:dateList){
            LocalDateTime min= LocalDateTime.of(date,LocalTime.MIN);
            LocalDateTime max=LocalDateTime.of(date,LocalTime.MAX);
            QueryWrapper wrapper=new QueryWrapper<>().eq("status",5)
                    .ge("delivery_time",min).le("delivery_time",max);
            List<Orders> list = list(wrapper);
            BigDecimal amount= BigDecimal.ZERO;
            if (!list.isEmpty()) {
                for (Orders order : list) {
                    amount=amount.add(order.getAmount());
                }
            }
            amountList.add(amount);
        }
        vo.setDateList(dateList);
        vo.setAmountList(amountList);
        return vo;
    }

    @Override
    public OrderStatisticsVO orders(LocalDate startTime, LocalDate endTime) {
        List<LocalDate> dateList=new ArrayList<>();
        dateList.add(startTime);
        LocalDate newDate=startTime;
        while (!newDate.equals(endTime)){
            newDate=newDate.plusDays(1);
            dateList.add(newDate);
        }
        List<Integer> validOrders=new ArrayList<>();
        List<Integer> totalOrders=new ArrayList<>();
        for (LocalDate date:dateList){
            LocalDateTime min= LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime max=LocalDateTime.of(date,LocalTime.MAX);
            QueryWrapper wrapper1=new QueryWrapper<>().ge("order_time",min).le("order_time",max);
            totalOrders.add(list(wrapper1).size());
            QueryWrapper wrapper2=new QueryWrapper<>().ge("order_time",min).le("order_time",max).eq("status",5);
            validOrders.add(list(wrapper2).size());
        }
        OrderStatisticsVO vo=OrderStatisticsVO.builder()
                .dateList(dateList).totalOrders(totalOrders)
                .validOrders(validOrders).build();
        return vo;
    }

    @Override
    public CountVO counts(LocalDate startTime, LocalDate endTime) {
        List<LocalDate> dateList = new ArrayList<>();
        dateList.add(startTime);
        LocalDate newDate = startTime;
        while (!newDate.equals(endTime)) {
            newDate = newDate.plusDays(1);
            dateList.add(newDate);
        }
        //获得这几天的全部订单
        List<Orders> list = new ArrayList<>();
        for (LocalDate date : dateList) {
            LocalDateTime min = LocalDateTime.of(date, LocalTime.MIN);
            LocalDateTime max = LocalDateTime.of(date, LocalTime.MAX);
            QueryWrapper wrapper = new QueryWrapper<>().ge("order_time", min).le("order_time", max);
            list.addAll(list(wrapper));
        }
        //获得所有订单的订单菜品
        List<OrderDetail> details = new ArrayList<>();
        if (!list.isEmpty()) {
            for (Orders order : list) {
                QueryWrapper queryWrapper = new QueryWrapper<>().eq("order_id", order.getId());
                details.addAll(iOrderDetailService.list(queryWrapper));
            }
        }
        List<OrderDishNameandCount> dishList = new ArrayList<>();
        for (OrderDetail detail : details) {
            Boolean flag = false;
            for (OrderDishNameandCount nameandCount : dishList) {
                if (nameandCount.getName().equals(detail.getName())) {
                    nameandCount.setCount(nameandCount.getCount() + detail.getNumber());
                    flag = true;
                }
            }
            if (!flag) {
                OrderDishNameandCount nameandCount = new OrderDishNameandCount();
                nameandCount.setName(detail.getName());
                nameandCount.setCount(detail.getNumber());
                dishList.add(nameandCount);
            }
        }
        dishList=dishList.stream().sorted(Comparator.comparing(OrderDishNameandCount::getCount)).toList();
        if (dishList.size()>10) {
            dishList=dishList.subList(0, 10);
        }
        CountVO countVO = new CountVO();
        List<Integer> counts = new ArrayList<>();
        List<String> names = new ArrayList<>();
        dishList.forEach(i -> {
            counts.add(i.getCount());
            names.add(i.getName());
        });
        countVO.setDishName(names);
        countVO.setDishCount(counts);
        return countVO;
    }

    @Override
    public List<Orders> day(LocalDate time) {
        LocalDateTime start=LocalDateTime.of(time,LocalTime.MIN);
        LocalDateTime end=LocalDateTime.of(time,LocalTime.MAX);
        QueryWrapper wrapper=new QueryWrapper<>().ge("order_time",start).le("order_time",end);
        List<Orders> list = list(wrapper);
        return list;
    }

    @Override
    @Transactional
    public String postOrder(OrderDTO dto) {

        //获得userid
        String token = httpServletRequest.getHeader("Authorization");
        Claims claims = JWTUtils.parseJWT(token);
        Long userid = claims.get("id", Long.class);

        Orders orders=new Orders();
        BeanUtils.copyProperties(dto,orders);
        orders.setStatus(1);
        orders.setOrderTime(LocalDateTime.now());
        AddressBook address = iAddressBookService.getById(dto.getAddressBookId());
        orders.setAddress(address.getProvinceName()+address.getCityName()+address.getDistrictName()+address.getDetail());
        orders.setConsignee(address.getConsignee());
        User user = iUserService.getById(userid);
        orders.setUserName(user.getName());
        orders.setUserId(userid);
        orders.setPhone(address.getPhone());
        orders.setPayStatus(0);
        //订单号随机生成
        ThreadLocalRandom random = ThreadLocalRandom.current();
        // 生成一个13位的随机数，需要注意这里的随机数可能包含负数，需要取绝对值
        long randomNumber = Math.abs(random.nextLong(1L, 1000000000000L));
        orders.setNumber(String.valueOf(randomNumber));
        save(orders);
        QueryWrapper wrapper=new QueryWrapper<>().eq("user_id",userid);


        //加入order_detail数据库
        List<ShoppingCart> shoppingCarts = iShoppingCartService.list(wrapper);
        for (ShoppingCart shoppingCart:shoppingCarts){
            OrderDetail orderDetail=new OrderDetail();
            BeanUtils.copyProperties(shoppingCart,orderDetail);
            orderDetail.setOrderId(orders.getId());
            iOrderDetailService.save(orderDetail);
        }
        iShoppingCartService.remove(wrapper);
        return orders.getNumber();
    }

    @Override
    public PayOrdersVO getByNumber(String number) {
        QueryWrapper wrapper=new QueryWrapper<>().eq("number",number);
        Orders one = getOne(wrapper);
        PayOrdersVO vo=new PayOrdersVO();
        BeanUtils.copyProperties(one,vo);
        vo.setOrderTime(one.getOrderTime());
        return vo;
    }

    /**
     * 订单支付
     * @param dto
     */
    @Override
    public void paySuccess(PaySuccessDTO dto) {
        QueryWrapper wrapper=new QueryWrapper<>().eq("number",dto.getNumber());
        Orders orders = getOne(wrapper);
        orders.setStatus(2);
        orders.setCheckoutTime(LocalDateTime.now());
        orders.setPayMethod(dto.getPayMethod());
        orders.setPayStatus(1);
        updateById(orders);
        try {
            webSocketServer.sendMessage("订单号"+orders.getNumber()+" 您有一份新订单，请及时查收！ ");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public List<OrderDetail> getOrdersDetailByNumber(String number) {
        QueryWrapper wrapper=new QueryWrapper<>().eq("number",number);
        Orders orders = getOne(wrapper);
        QueryWrapper wrapper1=new QueryWrapper<>().eq("order_id",orders.getId());
        List<OrderDetail> list = iOrderDetailService.list(wrapper1);
        return list;
    }

    @Override
    public void cancelOrders(String number) {
        UpdateWrapper wrapper=new UpdateWrapper<>().eq("number",number).set("status",6)
                .set("cancel_time",LocalDateTime.now());
        update(wrapper);
        try {
            webSocketServer.sendMessage("订单号"+number+" 已取消订单");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

    }

    @Override
    public void remind(Long id) {
        Orders orders = getById(id);
        try {
            webSocketServer.sendMessage("订单号"+orders.getNumber()+" 开始催单");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public void refundOrders(String number) {
        try {
            webSocketServer.sendMessage("订单号"+number+" 申请退款");
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    @Override
    public OrderDetailVO detailByNumber(String number) {
        QueryWrapper wrapper1=new QueryWrapper<>().eq("number",number);
        Orders orders = getOne(wrapper1);
        //根据订单号找到订单详情里面对应菜品
        QueryWrapper wrapper=new QueryWrapper<>().eq("order_id",orders.getId());
        List<OrderDetail> list = iOrderDetailService.list(wrapper);
        String s = dishString(orders.getId());

        //分别赋值
        OrderDetailVO orderDetailVO=new OrderDetailVO();
        BeanUtils.copyProperties(orders,orderDetailVO);
        orderDetailVO.setOrderDishes(s);
        orderDetailVO.setOrderDetailList(list);
        return orderDetailVO;
    }

    @Override
    public List<OrderDetailVO> getOrdersList(String search) {
        //获得userid
        String token = httpServletRequest.getHeader("Authorization");
        Claims claims = JWTUtils.parseJWT(token);
        Long userid = claims.get("id", Long.class);

        QueryWrapper wrapper=new QueryWrapper<>().eq("user_id",userid);
        List<Orders> list = list(wrapper);
        List<OrderDetailVO> detailVOS=new ArrayList<>();
        for (Orders orders:list){
            OrderDetailVO detail = detail(orders.getId());
            if (!search.equals("undefined")){
                QueryWrapper wrapper1=new QueryWrapper<>().like("name",search).eq("order_id",orders.getId());
                List<OrderDetail> searchList = iOrderDetailService.list(wrapper1);
                if (!searchList.isEmpty()){
                    detailVOS.add(detail);
                }
            }else{
            detailVOS.add(detail);}
        }

        return detailVOS;
    }


}
